%option noyywrap
%option nounput
%option noinput
%option yylineno
%top{
    #include <stdarg.h>
    #include "common.h"
    #include <malloc.h>
    #include <string.h>
}
%{
    extern dump_type_t dump_type;

    inline void dump_tokens(const char* format, ...){
        va_list args;
        va_start(args, format);
        if (dump_type == TOKENS)
            vfprintf(yyout, format, args);
        va_end(args);
    }

    /* Your code here, if desired (lab3). */
    class COLUMN{
    	public:
    	 int col;
    	 int now_line;
    	 COLUMN()
    	 {
    	   col=0;
    	   now_line=0;
    	 }
    	 
    	 int calculate_column(int line,int len)
    	 {
    	   if(now_line==line)
    	   {
    	     col+=len;
    	   }
    	   else // 开始，或到新行
    	   {
    	     now_line=line;
    	     col=len;
    	   }
    	   return col-len;
    	 
    	 }
    
    }column;
    
    
     
    class NODE{
    	public:
    	 char name[256]; // 变量名不超过255个字符
    	 NODE *prev,*next;
    };
    class ID_LIST{
    	public:
    	 NODE *head,*tail;
    	 int num;
    	 
    	 ID_LIST()
    	 {
    	   head=(NODE*)malloc(sizeof(NODE));
    	   head->next=head->prev=NULL;
    	   tail=head;
    	   num=0;
    	 }
    	 
    	 NODE* insert(char* s)
    	 {
    	   NODE *tmp=NULL;
    	   tmp=(NODE*)malloc(sizeof(NODE));
    	   strcpy(tmp->name,s);
    	   tail->next=tmp;
    	   tmp->prev=tail;
    	   tmp->next=NULL;
    	   tail=tmp;
    	   num++;
    	   return tmp;
    	 }
    	 
    }id_list;
    
    NODE* search_id(char*s)
    {
   	NODE* tmp=id_list.head;
   	for(;tmp!=NULL;tmp=tmp->next)
   	{
   	    if(tmp->name && !strcmp(tmp->name,s))//找到
   	    {return tmp;}
   	}
   	// 找不到
   	NODE* new_node=id_list.insert(s);
   	return new_node;
    
    }
    

%}

/* definitions section */
DECIMIAL ([1-9][0-9]*|0)
ID [[:alpha:]_][[:alpha:][:digit:]_]*
EOL (\r\n|\n|\r)
WHITE [\t ]
/*  Your code here (lab3). */
/* 八进制 */
OCTAL (0[0-7]+)           
/* 十六进制 */
HEXADECIMAL (0[xX][0-9A-Fa-f]+) 

%x BLOCK_COMMENT            
/* 块注释  */   
BLOCK_COMMENT_BEGIN "/*"           
/* 通配符+换行 */
BLOCK_COMMENT_ELEMENT .|\n         
BLOCK_COMMENT_END "*/" 
/* 行注释：以双斜杠开头，后跟若干个非换行的字符 */
LINE_COMMENT \/\/[^\n]*

%%
    /* rules section */
" " {
  column.calculate_column(yylineno,1);
}
"int" {
    int col=column.calculate_column(yylineno,strlen(yytext));
    dump_tokens("INT\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"void" {
    int col=column.calculate_column(yylineno,strlen(yytext));
    dump_tokens("VOID\t%s\t%d\n", yytext,yylineno,col);
}

"if" {
    int col=column.calculate_column(yylineno,strlen(yytext));
    dump_tokens("IF\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"else" {
    int col=column.calculate_column(yylineno,strlen(yytext));
    dump_tokens("ELSE\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"return" {
    int col=column.calculate_column(yylineno,strlen(yytext));
    dump_tokens("RETURN\t%s\t%d\t%d\n", yytext,yylineno,col);
}

    /* 关键字补充 */
"const" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("CONST\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"continue" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("CONTINUE\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"break" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("BREAK\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"while" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("WHILE\t%s\t%d\t%d\n", yytext,yylineno,col);
}

 /* 关系运算补充 */

"=" {
   int col=column.calculate_column(yylineno,strlen(yytext)); 
   dump_tokens("ASSIGN\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"==" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("EQUAL\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"!=" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("NOTEQUAL\t%s\t%d\t%d\n", yytext,yylineno,col);
}

">=" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("GREATEREQUAL\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"<=" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("LESSEQUAL\t%s\t%d\t%d\n", yytext,yylineno,col);
}

">" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("GREATER\t%s\t%d\t%d\n", yytext,yylineno,col);
}


"<" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("LESS\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"+" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("ADD\t%s\t%d\t%d\n", yytext,yylineno,col);
}
     /* 算术运算补充 */
"-" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("SUB\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"*" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("MUL\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"/" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("DIV\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"%" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("MOD\t%s\t%d\t%d\n", yytext,yylineno,col);
}

 /* 逻辑运算补充 */
"&&" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("AND\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"||" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("OR\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"!" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("NOT\t%s\t%d\t%d\n", yytext,yylineno,col);
}


";" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("SEMICOLON\t%s\t%d\t%d\n", yytext,yylineno,col);
}

 /* 符号补充 */
"," {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("COMMA\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"." {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("POINT\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"(" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("LPAREN\t%s\t%d\t%d\n", yytext,yylineno,col);
}

")" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("RPAREN\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"{" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("LBRACE\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"}" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("RBRACE\t%s\t%d\t%d\n", yytext,yylineno,col);
}

 /* 中括号补充 */
"[" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("LBRACKET\t%s\t%d\t%d\n", yytext,yylineno,col);
}

"]" {
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("RBRACKET\t%s\t%d\t%d\n", yytext,yylineno,col);
}


{DECIMIAL} {
   int decimal;
   decimal = atoi(yytext);
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("DECIMAL\t%s\t%d\t%d\t%d\n", yytext,yylineno,col,decimal);
}

{ID} {
    int col=column.calculate_column(yylineno,strlen(yytext));
    NODE*tmp=search_id(yytext);
    dump_tokens("ID\t%s\t%d\t%d\t%p\n", yytext,yylineno,col,tmp);
}

{EOL}

{WHITE}

    /*  Your code here (lab3). */
{LINE_COMMENT} {}
{BLOCK_COMMENT_BEGIN} {BEGIN BLOCK_COMMENT;}/* 开始块注释 */
<BLOCK_COMMENT>{BLOCK_COMMENT_ELEMENT} {}
<BLOCK_COMMENT>{BLOCK_COMMENT_END} {BEGIN INITIAL;} /* 使用BEGIN来切换到初始状态INITIAL */

{OCTAL} {
    int octal;    
    sscanf(yytext,"%o", &octal);  /* 将8进制数存到int中，转为10进制数 */
    int col=column.calculate_column(yylineno,strlen(yytext));
    dump_tokens("OCTAL\t%s\t%d\t%d\t%d\n", yytext,yylineno,col, octal);
}

{HEXADECIMAL} {
   int hexadecimal;    
   sscanf(yytext,"%x", &hexadecimal);  /* 将16进制数存到int中，转为10进制数 */
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("OCTAL\t%s\t%d\t%d\t%d\n", yytext,yylineno,col, hexadecimal);
}
/* 浮点数 */
FLOAT {DECIMIAL}(.{DECIMIAL})

{FLOAT} {
   char* end;
   float f; 
   f=strtof(yytext,&end);
   int col=column.calculate_column(yylineno,strlen(yytext));
   dump_tokens("FLOAT\t%s\t%d\t%d\t%f\n", yytext,yylineno,col,f);
}

%%
/* user code section */




